home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_110 / mint / bash110s.zoo / bash-1.10 / nojobs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-01  |  7.9 KB  |  358 lines

  1. /* The thing that makes children, remembers them, and contains wait loops. */
  2.  
  3. /* This file works under BSD, System V, minix, and Posix systems. */
  4.  
  5. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  6.  
  7. This file is part of GNU Bash, the Bourne Again SHell.
  8.  
  9. Bash is free software; you can redistribute it and/or modify it under
  10. the terms of the GNU General Public License as published by the Free
  11. Software Foundation; either version 1, or (at your option) any later
  12. version.
  13.  
  14. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  15. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17. for more details.
  18.  
  19. You should have received a copy of the GNU General Public License along
  20. with Bash; see the file COPYING.  If not, write to the Free Software
  21. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <signal.h>
  26. #include <setjmp.h>
  27. #include <errno.h>
  28.  
  29. #include "config.h"
  30. #include "general.h"
  31. #include "filecntl.h"
  32. #include "jobs.h"
  33.  
  34. #if !defined (USG) && !defined (_POSIX_VERSION)
  35. #  include <sgtty.h>
  36. #else
  37. #  if defined (USG)
  38. #    include <termio.h>
  39. #    include <sys/ttold.h>
  40. #  else 
  41. #    include <termios.h>
  42. #  endif
  43. #endif /* !USG && !_POSIX_VERSION */
  44.  
  45. #ifndef SIGABRT
  46. #define SIGABRT SIGIOT
  47. #endif
  48.  
  49. #if defined (USG) || defined (_POSIX_VERSION)
  50. #define killpg(pg, sig)        kill(-(pg),(sig))
  51. #endif
  52.  
  53. #if defined (USG)
  54. #define siginterrupt(sig, code)
  55. #endif
  56.  
  57. pid_t last_made_pid = (pid_t)-1;
  58. pid_t last_asynchronous_pid = (pid_t)-1;
  59.  
  60. extern int errno;
  61.  
  62. /* Initialize the job control mechanism, and set up the tty stuff. */
  63. initialize_jobs ()
  64. {
  65.   get_tty_state ();
  66. }
  67.  
  68. /* Setup this shell to handle C-C, etc. */
  69. initialize_job_signals ()
  70. {
  71.   extern int login_shell;
  72.   extern sighandler sigint_sighandler ();
  73.  
  74.   signal (SIGINT, sigint_sighandler);
  75.  
  76.   /* If this is a login shell we don't wish to be disturbed by
  77.      stop signals. */
  78.   if (login_shell)
  79.     {
  80. #ifdef SIGTSTP
  81.       signal (SIGTSTP, SIG_IGN);
  82.       signal (SIGTTOU, SIG_IGN);
  83.       signal (SIGTTIN, SIG_IGN);
  84. #endif
  85.     }
  86. }
  87.  
  88. /* Fork, handling errors.  Returns the pid of the newly made child, or 0.
  89.    COMMAND is just for remembering the name of the command; we don't do
  90.    anything else with it.  ASYNC_P says what to do with the tty.  If
  91.    non-zero, then don't give it away. */
  92. pid_t
  93. make_child (command, async_p)
  94.      char *command;
  95.      int async_p;
  96. {
  97.   pid_t pid;
  98.  
  99.   /* Discard saved memory. */
  100.   if (command)  
  101.     free (command);
  102.  
  103.   /* Make new environment array if neccessary. */
  104.   maybe_make_export_env ();
  105.  
  106.   /* Create the child, handle severe errors. */
  107.   if ((pid = fork ()) < 0)
  108.     {
  109.       report_error ("fork: %s", strerror (errno));
  110.  
  111.       throw_to_top_level ();
  112.     }
  113.  
  114.   if (!pid)
  115.     {
  116.       /* Cancel shell traps. */
  117.       restore_original_signals ();
  118.  
  119.       /* Ignore INT and QUIT in asynchronous children. */
  120.       if (async_p)
  121.     {
  122.       signal (SIGINT, SIG_IGN);
  123.       signal (SIGQUIT, SIG_IGN);
  124.       last_asynchronous_pid = getpid ();
  125.     }
  126.       else
  127.     {
  128. #if defined (SIGTSTP)
  129.       signal (SIGTSTP, SIG_DFL);
  130.       signal (SIGTTIN, SIG_DFL);
  131.       signal (SIGTTOU, SIG_DFL);
  132. #endif
  133.     }
  134.     }
  135.   else
  136.     {
  137.       /* In the parent. */
  138.       last_made_pid = pid;
  139.  
  140.       if (async_p)
  141.     last_asynchronous_pid = pid;
  142.     }
  143.   return (pid);
  144. }
  145.  
  146. /* Wait for a single pid (PID) and return its exit status. */
  147. wait_for_single_pid (pid)
  148.      pid_t pid;
  149. {
  150.   pid_t got_pid;
  151.   WAIT status;
  152.  
  153.   /* Make sure that the process we are waiting for is valid. */
  154.   if ((kill (pid, 0) < 0) && errno == ESRCH)
  155.     return (127);
  156.  
  157.   siginterrupt (SIGINT, 1);
  158.   while ((got_pid = wait (&status)) != pid)
  159.     {
  160.       if (got_pid < 0)
  161.     {
  162.       if (errno != EINTR && errno != ECHILD)
  163.         {
  164.           siginterrupt (SIGINT, 0);
  165.           file_error ("wait");
  166.         }
  167.       break;
  168.     }
  169.     }
  170.   siginterrupt (SIGINT, 0);
  171.   QUIT;
  172. }
  173.  
  174. /* Wait for all of the shell's children to exit. */
  175. wait_for_background_pids ()
  176. {
  177.   /* If we aren't using job control, we let the kernel take care of the
  178.      bookkeeping for us.  wait () will return -1 and set errno to ECHILD 
  179.      when there are no more unwaited-for child processes on both
  180.      4.2 BSD-based and System V-based systems. */
  181.  
  182.   siginterrupt (SIGINT, 1);
  183.   while (1)
  184.     {
  185.       pid_t got_pid;
  186.       WAIT status;
  187.  
  188.       while ((got_pid = wait(&status)) != -1)  /* wait for ECHILD */
  189.     ;
  190.       if (errno != EINTR && errno != ECHILD)
  191.     {
  192.       siginterrupt (SIGINT, 0);
  193.       file_error("wait");
  194.     }
  195.       break;
  196.     }
  197.   siginterrupt (SIGINT, 0);
  198.   QUIT;
  199. }
  200.  
  201. /* Wait for pid (one of our children) to terminate. */
  202. int
  203. wait_for (pid)
  204.      pid_t pid;
  205. {
  206.   extern int interactive;
  207.   int return_val;
  208.   pid_t got_pid;
  209.   WAIT status;
  210.  
  211.   /* Make sure that the process we are waiting for is valid. */
  212.   if ((kill (pid, 0) < 0) && (errno == ESRCH))
  213.     return (0);
  214.  
  215.   siginterrupt (SIGINT, 1);
  216.   while ((got_pid = wait (&status)) != pid)
  217.     {
  218.       if (got_pid < 0 && errno == ECHILD)
  219.     {
  220. #if !defined (_POSIX_VERSION)
  221.       status.w_termsig = status.w_retcode = 0;
  222. #else
  223.       status = 0;
  224. #endif /* _POSIX_VERSION */
  225.       break;
  226.     }
  227.       else if (got_pid < 0 && errno != EINTR)
  228.     programming_error ("got errno %d while waiting for %d", errno, pid);
  229.     }
  230.   siginterrupt (SIGINT, 0);
  231.  
  232. #if 0
  233.   /* Not needed because the builtin wait does not go through this path. */
  234.   if (interactive)    /* allow the user to ^C out of the builtin wait */
  235.     QUIT;
  236. #endif
  237.  
  238.   /* Default return value. */
  239.   /* ``a full 8 bits of status is returned'' */
  240.   if (WIFSIGNALED (status))
  241.     return_val = 128 + WTERMSIG (status);
  242.   else
  243.     return_val = WEXITSTATUS (status);
  244.                             
  245.   if (!WIFSTOPPED (status) && WIFSIGNALED (status) &&
  246.       (WTERMSIG (status) != SIGINT))
  247.     {
  248.       extern char *sys_siglist[];
  249.       fprintf (stderr, "%s", sys_siglist[WTERMSIG (status)]);
  250.       if (WIFCORED (status))
  251.     fprintf (stderr, " (core dumped)");
  252.       fprintf (stderr, "\n");
  253.     }
  254.  
  255.   if (WIFSIGNALED (status) || WIFSTOPPED (status))
  256.     set_tty_state ();
  257.   else
  258.     get_tty_state ();
  259.                             
  260.   return (return_val);
  261. }
  262.  
  263. /* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
  264.    If PID does belong to a job, and the job is stopped, then CONTinue the
  265.    job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
  266.    then kill the process group associated with PID. */
  267. int
  268. kill_pid (pid, signal, group)
  269.      pid_t pid;
  270.      int signal, group;
  271. {
  272.   int result;
  273.  
  274.   if (group)
  275.     result = killpg (pid, signal);
  276.   else
  277.     result = kill (pid, signal);
  278.  
  279.   return (result);
  280. }
  281.  
  282. #if defined (_POSIX_VERSION)
  283. static struct termios shell_tty_info;
  284. #else
  285. #  if defined (USG)
  286. static struct termio shell_tty_info;
  287. #  else
  288. static struct sgttyb shell_tty_info;
  289. #  endif /* USG */
  290. #endif /* _POSIX_VERSION */
  291.  
  292. static int got_tty_state = 0;
  293.  
  294. /* Fill the contents of shell_tty_info with the current tty info. */
  295. get_tty_state ()
  296. {
  297.   int tty = open ("/dev/tty", O_RDONLY);
  298.   if (tty != -1)
  299.     {
  300.    
  301. #if defined (_POSIX_VERSION)
  302.       tcgetattr (tty, &shell_tty_info);
  303. #else
  304. #  if defined (USG)
  305.       ioctl (tty, TCGETA, &shell_tty_info);
  306. #  else
  307.       ioctl (tty, TIOCGETP, &shell_tty_info);
  308. #  endif
  309. #endif
  310.       close (tty);
  311.       got_tty_state = 1;
  312.     }
  313. }
  314.  
  315. /* Make the current tty use the state in shell_tty_info. */
  316. set_tty_state ()
  317. {
  318.   int tty = open ("/dev/tty", O_RDONLY);
  319.   if (tty != -1)
  320.     {
  321.       if (!got_tty_state)
  322.     {
  323.       close (tty);
  324.       return;
  325.     }
  326. #if defined (_POSIX_VERSION)
  327.       tcsetattr (tty, TCSADRAIN, &shell_tty_info);
  328. #else
  329. #  if defined (USG)
  330.       ioctl (tty, TCSETAW, &shell_tty_info);  /* Wait for output, no flush */
  331. #  else
  332.       ioctl (tty, TIOCSETN, &shell_tty_info);
  333. #  endif
  334. #endif
  335.       close (tty);
  336.     }
  337. }
  338.  
  339. /* Give the terminal to PGRP.  */
  340. give_terminal_to (pgrp)
  341.      pid_t pgrp;
  342. {
  343. }
  344.  
  345. /* Stop a pipeline. */
  346. stop_pipeline (async, ignore)
  347.      int async;
  348.      char *ignore;
  349. {
  350. }
  351.  
  352. /* Print descriptive information about the job with leader pid PID. */
  353. describe_pid (pid)
  354.      pid_t pid;
  355. {
  356.   fprintf (stderr, "<%d>\n", (int) pid);
  357. }
  358.